
#include "stdafx.h"
#include "BaseLPCArray.h"

template <typename VALUE_TYPE>
void CBaseLPCArray<VALUE_TYPE>::build(VALUE_TYPE s, VALUE_TYPE sepStr)
{
	if (maxLength <= 0)
	{
		clear();
		for (VALUE_TYPE p = s; p; p += getLength(sepStr))
		{
			count++; p = find(p, sepStr); if (!p) break;
		}
		if (count)
		{
			intptr_t ncount = ((count + 15) >> 4) << 4;
			str = (VALUE_TYPE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ncount*sizeof(VALUE_TYPE));
			for (intptr_t i = 0, j = 0; i < count; i++)
			{
				VALUE_TYPE p = find(s + j, sepStr); intptr_t k = p ? (intptr_t)(p - s) : getLength(s);
				intptr_t sLen = (k - j)*getSingleCharLength();
				LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sLen + 4);
				memcpy_s(buf, sLen + 4, s + j, sLen);
				str[i] = (VALUE_TYPE)buf; j = k + getLength(sepStr);
			}
		}
	}
	else
	{
		intptr_t i = 0;
		if (s)
		{
			for (intptr_t j = 0; s[j] && i < count; i++)
			{
				VALUE_TYPE p = find(s + j, sepStr); intptr_t k = p ? (intptr_t)(p - s) : getLength(s);
				LPSTR buf = (LPSTR)(str[i]);
				if (buf)
				{
					intptr_t sLen = min(maxLength - 4, (k - j)*getSingleCharLength());
					memcpy_s(buf, maxLength, s + j, sLen); 
					ZeroMemory((LPVOID)(buf + sLen), maxLength - sLen);
				}
				j = k + (p ? getLength(sepStr) : 0);
			}
		}
		for (; i < count; i++) if (str[i]) ZeroMemory((LPVOID)str[i], maxLength);;
	}
}

template <typename VALUE_TYPE>
void CBaseLPCArray<VALUE_TYPE>::build(VALUE_TYPE s, char sepChar)
{
	if (maxLength <= 0)
	{
		clear();
		for (VALUE_TYPE p = s; p;)
		{
			count++; p = find(p, sepChar); if (!p) break;
			if (sepChar) p++;
		}
		if (count)
		{
			intptr_t ncount = ((count + 15) >> 4) << 4;
			str = (VALUE_TYPE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ncount*sizeof(VALUE_TYPE));
			for (intptr_t i = 0, j = 0; i < count; i++)
			{
				VALUE_TYPE p = find(s + j, sepChar); intptr_t k = p ? (intptr_t)(p - s) : getLength(s);
				intptr_t sLen = (k - j)*getSingleCharLength();
				LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sLen + 4);
				memcpy_s(buf, sLen + 4, s + j, sLen);
				str[i] = (VALUE_TYPE)buf; j = k + (sepChar == 0 ? 0 : 1);
			}
		}
	}
	else
	{
		intptr_t i = 0;
		if (s)
		{
			for (intptr_t j = 0; s[j] && i < count; i++)
			{
				VALUE_TYPE p = find(s + j, sepChar); intptr_t k = p ? (intptr_t)(p - s) : getLength(s);
				LPSTR buf = (LPSTR)str[i];
				if (buf)
				{
					intptr_t sLen = min(maxLength - 4, (k - j)*getSingleCharLength());
					memcpy_s(buf, maxLength, s + j, sLen);
					ZeroMemory((LPVOID)(buf + sLen), maxLength - sLen);
				}
				j = k + (p ? 1 : 0);
			}
		}
		for (; i < count; i++) if (str[i]) ZeroMemory((LPVOID)str[i], maxLength);;
	}
}

template <typename VALUE_TYPE>
void CBaseLPCArray<VALUE_TYPE>::clear()
{
	if (maxLength <= 0)
	{
		if (str)
		{
			for (intptr_t i = 0; i < count; i++) if (str[i]) HeapFree(GetProcessHeap(), 0, (LPVOID)str[i]);
			HeapFree(GetProcessHeap(), 0, (LPVOID)str);
		}
		count = 0; str = nullptr;
	}
	else
	{
		for (intptr_t i = 0; i < count; i++) if (str[i]) ZeroMemory((LPVOID)str[i], maxLength);
	}
}

template <typename VALUE_TYPE>
void CBaseLPCArray<VALUE_TYPE>::operator =(const CBaseLPCArray<VALUE_TYPE>& src)
{
	maxLength = -1; clear();
	count = src.count; maxLength = src.maxLength;
	if (count <= 0) return;
	if (maxLength <= 0)
	{
		intptr_t ncount = ((count + 15) >> 4) << 4;
		str = (VALUE_TYPE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ncount*sizeof(VALUE_TYPE));
		for (intptr_t i = 0; i < count; i++) if (src.str && src.str[i])
		{
			intptr_t sLen = getLength(src.str[i])*getSingleCharLength();
			LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sLen + 4);
			memcpy_s(buf, sLen + 4, src.str[i], sLen);
			str[i] = (VALUE_TYPE)buf;
		}
	}
	else
	{
		intptr_t ncount = ((count + 15) >> 4) << 4;
		str = (VALUE_TYPE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ncount*sizeof(VALUE_TYPE));
		for (intptr_t i = 0; i < count; i++)
		{
			str[i] = (VALUE_TYPE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, maxLength);
			if (src.str && src.str[i]) memcpy_s((LPVOID)str[i], maxLength, src.str[i], maxLength);
		}
	}
}

template <typename VALUE_TYPE>
void CBaseLPCArray<VALUE_TYPE>::add(VALUE_TYPE value, bool copyValue)
{
	insert(count, value, copyValue);
}

template <typename VALUE_TYPE>
VALUE_TYPE CBaseLPCArray<VALUE_TYPE>::remove(intptr_t index, bool delValue)
{
	if (index < 0 || index >= count) return nullptr;
	VALUE_TYPE p = str[index];
	for (intptr_t i = index; i < count - 1; i++) str[i] = str[i + 1];
	count--; str[count] = nullptr;
	if (delValue)
	{
		if (p) HeapFree(GetProcessHeap(), 0, (LPVOID)p);
		return nullptr;
	}
	else
		return p;
}

template <typename VALUE_TYPE>
intptr_t CBaseLPCArray<VALUE_TYPE>::insert(intptr_t index, VALUE_TYPE value, bool copyValue)
{
	if (index < 0) index = 0;
	if (index > count) index = count;
	if ((count & 0xf) == 0)
	{
		intptr_t oldLen = count*sizeof(VALUE_TYPE), newLen = (count + 16)*sizeof(VALUE_TYPE);
		VALUE_TYPE *p = str; str = (VALUE_TYPE *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newLen);
		if (p)
		{
			memcpy_s(str, newLen, p, oldLen);
			HeapFree(GetProcessHeap(), 0, (LPVOID)p);
		}
	}
	for (intptr_t i = count; i > index; i--) str[i] = str[i - 1];
	if (value && copyValue)
	{
		intptr_t cLen = getLength(value)*getSingleCharLength() + 4;
		intptr_t sLen = maxLength <= 0 ? cLen : maxLength;
		LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sLen);
		memcpy_s(buf, sLen, value, cLen);
		str[index] = (VALUE_TYPE)buf;
	}
	else
		str[index] = value;
	count++;
	return index;
}
